package cn.flant.proxy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ProxyUtil {

	private final static Class<?>[] constructorParams = { InvocationHandler.class };

	@SuppressWarnings("unchecked")
	public static <T> Class<T> getProxyClass(Class<T> intf) {
		return (Class<T>) Proxy.getProxyClass(intf.getClassLoader(), new Class<?>[] { intf });
	}

	@SuppressWarnings("unchecked")
	public static <T> Class<T> getProxyClass(Class<T>[] intfs) {
		return (Class<T>) Proxy.getProxyClass(intfs.getClass().getClassLoader(), intfs);
	}

	@SuppressWarnings("unchecked")
	public static <T> T newProxyInstance(Class<T> intf, InvocationHandler handler) throws Throwable {
		return (T) Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class<?>[] { intf }, handler);
	}

	@SuppressWarnings("unchecked")
	public static <T> T newProxyInstance(Class<T>[] intfs, InvocationHandler handler) throws Throwable {
		return (T) Proxy.newProxyInstance(handler.getClass().getClassLoader(), intfs, handler);
	}

	public static <T> T proxyClassInstance(Class<T> proxyClass, InvocationHandler handler) throws Throwable {
		if (proxyClass == null) {
			return null;
		} else if (!Proxy.isProxyClass(proxyClass)) {
			throw new IllegalArgumentException(proxyClass.getSimpleName() + " is not a proxy class");
		}
		Constructor<T> cons = proxyClass.getConstructor(constructorParams);
		return (T) cons.newInstance(new Object[] { handler });
	}

}
